/*
|-----------------------------------------------------------------------------|
| Overall ANTLR Grammar File Structure                                        |
|-----------------------------------------------------------------------------|
| «grammarType» grammar name;
|   «optionsSpec»     = options { ... }
|   «tokensSpec»      = tokens { ... }
|   «attributeScopes» = «@action-scope-name::action-name» { ... }
|   «actions»
|   // rules
|   rule1 : ... ;
|   rule2 : ... ;
|   ...
|_____________________________________________________________________________|
|   «grammarType»         = ( lexer | parser | tree | <empty> )
|   «optionsSpec»         = options { ... }
|   «tokensSpec»          = tokens { ... }
|   «attributeScopes»     = 
|   «actions»             = @«action-scope-name»::«action-name» { ... }
|    «action-scope-name» = ( lexer | parser | tree | <empty> = parser )
|    «action-name»       = ( header | members | rulecatch | synpredgate )
|-----------------------------------------------------------------------------|
*/
lexer grammar CLexer;

  options {
    language = Java;
  }// options
  
  @lexer::header {
    package pl.p06.antlr3;
  }//header
  @lexer::members {
  }// members

//= Lexer Rules C ============================================================|
   /* Tipos de datos */
   Void     : 'void';
   Int      : 'int';
   Char     : 'char';
   Float    : 'float';
   Short    : 'short';
   Signed   : 'signed';
   Long     : 'long';
   Double   : 'double';
   Unsigned : 'unsigned';

   /* Palabras reservadas */
   Include  : 'include';
   Define   : 'define';
   Typedef  : 'typedef';
   If       : 'if';
   Else     : 'else';
   While    : 'while';
   For      : 'for';
   Do       : 'do';
   Switch   : 'switch';
   Case     : 'case';
   Default  : 'default';
   Break    : 'break';
   Continue : 'continue';
   Goto     : 'goto';
   True     : 'true';
   False    : 'false';
   Return   : 'return';   
   Sizeof   : 'sizeof';
   Volatile : 'volatile';
   Const    : 'const';
   Enum     : 'enum';
   Union    : 'union';
   Struct   : 'struct';
   Extern   : 'extern';
   Static   : 'static';
   Auto     : 'auto';
   Register : 'register';

  /* Nueva línea */
  fragment NewLine: '\r'? '\n';

  /* Espacios */
  WhiteSpace : (' '|'\r'|'\t'|'\u000C'|'\n') { $channel=HIDDEN; skip(); };

  /* Dígitos */
  fragment Digit: ('0'..'9') ;
  fragment HexDigit : (Digit|'a'..'f'|'A'..'F') ;
  fragment OctalDigit : ('0'..'7') ;

  /* Números */
  HexLiteral : '0' ('x'|'X') HexDigit+ ;
  DecimalLiteral : ('0' | '1'..'9' Digit*) ;
  OctalLiteral : '0' (OctalDigit)+ ;
  fragment Exponent : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
  FloatingPointLiteral :   (Digit)+ '.' (Digit)* Exponent? ;

  /* Letras */
  fragment LetterLower: ('a'..'z');
  fragment LetterUpper: ('A'..'Z');
  fragment Letter: (LetterLower|LetterUpper|'_');

  /* Identificadores */
  Identifier: Letter (Letter | Digit)*;

  /* Cadenas */
  fragment EscapeSequence
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   OctalEscape
    ;
  fragment OctalEscape
    :   '\\' ('0'..'3') OctalDigit OctalDigit
    |   '\\' OctalDigit OctalDigit
    |   '\\' OctalDigit
    ;
  CharacterLiteral: '\'' ( EscapeSequence | ~('\''|'\\') ) '\'' ;
  StringLiteral: '"' (options {greedy=false;}: (EscapeSequence|~('\\'|'"')) )* '"';


  /* Separadores */
  LeftParenthesis     : '(';
  RightParenthesis    : ')';
  LeftBracket         : '{';
  RightBracket        : '}';
  LeftSquareBracket   : '[';
  RightSquareBracket  : ']';
  Colon               : ':';
  SemiColon           : ';';
  Comma               : ',';
  Dot                 : '.';

  /* Operadores */
  Equal           : '==';
  NotEqual        : '!=';
  LessEqual       : '<=';
  GreaterEqual    : '>=';
  LeftShift       : '<<';
  RightShift      : '>>';
  And             : '&&';
  Or              : '||';
  MultiplyEqual   : '*=';
  DivideEqual     : '/=';
  ModEqual        : '%=';
  AddEqual        : '+=';
  SubEqual        : '-=';
  LeftShiftEqual  : '<<=';
  RightShiftEqual : '>>=';
  AndEqual        : '&=';
  ExpEqual        : '^=';
  OrEqual         : '|=';
  Increase        : '++';
  Decrease        : '--';
  Aim             : '->';
  Ellipsis        : '...';

  Assing        : '=';
  Not           : '!';
  Less          : '<';
  Greater       : '>';
  Plus          : '+';
  Minus         : '-';
  Asterisk      : '*';
  Ampersand     : '&';
  Stick         : '|';
  Slash         : '/';
  Question      : '?';
  NumberSign    : '#';
  Caret         : '^';
  Percent       : '%';
  Tilde         : '~';

  /* Comentarios */
  CommentLine
    : '//' ~('\n'|'\r')* NewLine  { $channel=HIDDEN; skip(); } 
    ;
  NestedCommentBlock
    : '/*' (options {greedy=false;} : (NestedCommentBlock | .))* '*/'
      { $channel=HIDDEN; skip(); }
    ;